package org.project.d.starter.network;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.project.d.network.start.ServiceException;
import org.project.d.network.start.TcpServer;
import org.project.d.network.start.UdpServer;
import org.project.d.starter.network.properties.ProjectNetworkProperties;
import org.project.d.starter.network.properties.TcpConfig;
import org.project.d.starter.network.properties.UdpConfig;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;

import java.util.concurrent.CompletableFuture;


/**
 * @author lin
 * @version V1.0
 * @description
 * @date 2020/9/22 3:27 下午
 */
@Slf4j
public class ProjectNetworkAutoRegister {
    protected ProjectNetworkProperties projectNetworkProperties;
    protected ApplicationContext applicationContext;
    private ServerStartResult serverStartResult = new ServerStartResult();
    @Data
    public class ServerStartResult {
        private boolean tcpStart;
        private CompletableFuture<Boolean> tcpStartEnd;
        private int tcpPort;
        private String tcpHost;
        private String tcpServerName;
        private boolean udpStart;
        private CompletableFuture<Boolean> udpStartEnd;
        private int udpPort;
        private String udpHost;
        private String udpServerName;
    }

    public ProjectNetworkAutoRegister(ProjectNetworkProperties projectNetworkProperties, ApplicationContext applicationContext) {
        this.projectNetworkProperties = projectNetworkProperties;
        this.applicationContext = applicationContext;
    }

    public ServerStartResult getServerStartResult() {
        return serverStartResult;
    }

    public void regist() {
        if (projectNetworkProperties == null) {
            return;
        }
        serverStartResult.setTcpStart(projectNetworkProperties.isStartTcpServer());
        serverStartResult.setUdpStart(projectNetworkProperties.isStartUdpServer());
        serverStartResult.setTcpServerName(projectNetworkProperties.getTcpServerName());
        serverStartResult.setUdpServerName(projectNetworkProperties.getUdpServerName());
        if (projectNetworkProperties.isStartTcpServer()) {
            TcpConfig tcpConfig;
            CompletableFuture<Boolean> tcpStart;
            try {
                tcpConfig = applicationContext.getBean(TcpConfig.class);
                TcpServer tcpServer = new TcpServer(projectNetworkProperties.getTcpPort(), projectNetworkProperties.getTcpHost(), tcpConfig.getChannelHandlerInit(), tcpConfig.getChannelServerOptionInit());
                tcpServer.init();
                tcpStart = tcpServer.start();
            } catch (BeansException e) {
                log.info("tcpServer start is enable,but spring context not find TcpConfig use default config");
                TcpServer tcpServer = new TcpServer(projectNetworkProperties.getTcpPort(), projectNetworkProperties.getTcpHost());
                tcpServer.init();
                tcpStart = tcpServer.start();
            }
            serverStartResult.setTcpPort(projectNetworkProperties.getTcpPort());
            serverStartResult.setTcpHost(projectNetworkProperties.getTcpHost());
            serverStartResult.setTcpStartEnd(tcpStart);
        }
        if (projectNetworkProperties.isStartUdpServer()) {
            UdpConfig udpConfig;
            CompletableFuture<Boolean> start;
            try {
                udpConfig = applicationContext.getBean(UdpConfig.class);
                UdpServer udpServer = new UdpServer(projectNetworkProperties.getUdpPort(), projectNetworkProperties.getUdpHost(), udpConfig.getChannelHandlerInit(), udpConfig.getChannelOptionInit());
                udpServer.init();
                start = udpServer.start();
            } catch (BeansException e) {
                log.info("udpConfig start is enable,but spring context not find UdpConfig use default config");
                UdpServer udpServer = new UdpServer(projectNetworkProperties.getUdpPort(), projectNetworkProperties.getUdpHost());
                udpServer.init();
                start = udpServer.start();
            }
            serverStartResult.setUdpPort(projectNetworkProperties.getUdpPort());
            serverStartResult.setUdpHost(projectNetworkProperties.getUdpHost());
            serverStartResult.setUdpStartEnd(start);
        }
    }

}
